/**自定义一个简单的脚手架 
 * 
 * 创建自定义全局命令
 * 命令参数的接受处理
 * 中端交互
 * 下载远程项目代码
 * 项目初始化完成提示
*/

/**
 * 1.自定义全局命令
 * 2.先在目录下创建bin文件夹 在里面创建cli.js（这个就是代码文件）  后在根路径下执行npm init -y
 * 3.后使用npm link 全局挂载挂载 
 * 4.在cli文件写入指定脚本的解释程序（#! /usr/bin/env node）
 * 5.添加命令选项  process.argv获取一个数组  进行获取传入的参数
 * 6.使用工具包获取传入的参数 使用commander处理命令参数 --help
 * 7.使用模块化抽离代码 help command action 
 * 8.实现类似与问你问题的内容 与使用者进行问答的交互 使用  inquirer(注意有的要使用inquirer.default)  命令行交互工具
 * 9.根据用户答案不同下载不同的仓库代码下载远程仓库模板代码 使用工具npm install download-git-repo  
 * 10.下载等待提示交互 下载ora 
 * 11. 命令行样式输出 下载chalk
 */


/**
 * 关于express
 * 1. const { promisify } = require('util') 可以把方法转换成promise类的方法
 * 2.app.use(express.urlencoded()) 让后端接受urlencoded类型的参数
 * 3.app.use(express.json()) 接受json格式的数据
 * 4.小练习  通过增删改查 修改yonghu数据
 */

/**
 * 
 * 使用MongoDB
 * 1.安装使用mongoDB show dbs   use mytest   db.cc.insert({x:1})
 * 2.增删改查操作 insertone insertmany([])
 * 3.db.cc.find({age:{$gt:15}})  db.cc.findOne({age:{$gt:15}})
 * 4.db.cc.updateOne({username:'ls},{$set:{age:30}})
 * 5.db.cc.deleteOne({username:'ls})
 * 6.node 连接数据库 npm搜索mongoDB
 * 7.node 里面的方法都是异步的方法  需要使用async await 进行
 * 
 */


/**
 * 
 * 1.Express中间件的概念与基本应用
 * 2.举了个例子 app.use((req,res,next)=>{console.log(req.url); next()})
 * 3.中间件的位置要放在最前面
 * 4.有哪些中间件 应用程序级别  路由级别 错误级别   
 * 5.应用程序级别  app.use((req,res,next)=>{})
 *    6.请求方法中间件app.get('/user',(req,res,next)=>{})
 *    7.app.get('/user',(req,res,next)=>{next()},()=>{在往下处理})
 * 8.路由级别中间件
 *    9.const router = express.Router() 
 *    10.app.use('前缀',router)
 * 11.错误级别
 *    12. 放在所有之后（如果没有设置该请求路径） app.use((req,res,next)=>{res.status(404)})
 *    13. app.use((err,req,res,next)) y有四个参数的会获取到其他的语法错误
 * 14.内置中间件
 *    15.app.use(json()) 等等   解析接口返回的数据格式
 * 16.第三方中间件  比如跨域
 * 
 * 
 * 17 app.all('/xxx',(req,res)) 接受所有请求
 * 18 app.get('/us?er) ?前面的可写可不写 app.get('/us+er)  +前面可以写多个s
 * 19 路由的链式调用 app.get().post()
 * 20 res.download() res.json() res.end() 重定向 res.redirect() res.render() res.status() res.sendStatus()
 * 
 * 21.基础的设置 所需要的中间件  跨域(cors) 解析数据 ,日志记录(morgan),设置路由模块，
 * 设置业务逻辑模块
 * 
 * 22数据处理模块  mongoose 基于mongodb的方法
 * 23.用户密码加密问题 md5 crypto
 * 24.数据的唯一性  也是使用express-validator 的自定义验证功能  使用数据库查询  
 * 25.使用 express-validator 进行数据验证 也要使用模块化
 * 26.接口 Restful 规范
 * 
 * 27.用户登陆信息对比  在useModelscheme中添加 select:false 表示返回的不包含这个字段
 * set 表示额外处理这个数据
 * 28.jwt 身份登陆验证 jsonwebtoken 库
 * 29.用户登陆认证与接口鉴权    
 * 30。uuid vscode  插件生成私钥id
 * 31.在util 生成token  解析token(需要做成路由的中间件)
 * 32.req.use 对req的修改会传递到下一个req中
*/


/**
 * 
 * 文件上传与管理
 * 
 * 1.在mongo usemodel添加channeldes(频道字段) cover(频道封面) 频道
 * 2.创建put方法 修改当前用户信息，并添加用户修改的控制器 对输入的数据进行验证 查看修改的信息是否被注册过了
 * 3.在控制器内修改仓库的数据 findByIdandUpdate(id,data，{new:true}) 返回的是就的数据
 * 
 * 4.文件上传操作  插件 Multer 文件上传的中间间  用户头像上传 同步到更路径的public文件夹内
 * 5.上传成功后修改文件后缀名 后修改到数据库
 * 6.express 处理静态资源   使用内置中间件 
 * 7.视频和图片的处理不一样的  视频需要审核，防下载  通过第三包一次性处理   使用阿里云Vod服务
 * 
 * 
 * 8. VoD视频点播服务 观看操作手册
 * 9. 在express  建立获取上传凭证的路由地址  通过凭证真的上传视频 所以服务端就是只要提供上传凭证 然后数据库只有存储视频id就可以啦
 * 10. 使用上传凭证 需要在前端使用上传 阿里云有提供小demo
 * 11. 上传成功后 新建集合存放视频  包括标题，描述，封面，vodid,用户信息（需要和用户表关联 tyep: mongoose.ObjectId ref:'User(和集合关联)）
 * 
 * 
 * 
 * 12视频列表 的分页显示 排序  关联查询（populate(集合)） 获取总条数
 * 
 * 
 * 
 * 
 * 13获取视频详情 通过vod的视频的id populate(集合,'id'...需要的参数)
 * 14. 视频的播放 有没有点赞 播放数量 有没有关注 （登陆和未登录的处理） 获取视频详情分成分成登陆和未登录两种
 * 15. 把接口做成半登陆状态 把jwt包装成一个方法返回一个函数  变成可以传递参数(required = true)
 * 16. 处理登陆未登录的状态
 * 
 * 
 * 17.频道订阅取消订阅  新建路由 subscribe/:userId  需要登陆验证 自己不能关注自己
 * 18.登陆的id 要关注的id  
 * 19.创建关注关系的集合   user谁  channle关注谁 在userModele 添加关注者的数量
 * 20.判断要关注的人是否存在  判断是否已经关注
 * 
 * 21获取频道信息  判断是否登陆 判断是否已经关注过的 如果已经关注  添加对象数据 isSubscribr
 * 22使用lodash 的 pick的方法
 * 
 * 
 * 23.关注列表和粉丝列表
 * 24.getsubscribt/:userid  不用登陆验证  看我关注了谁 也要使用管理集合的功能
 * 25.getchannnel 通过登陆验证获取uerid 还要对列表进行分页
 * 
 * 
 * 26.添加视频评论  使用到video的集合 /comment/:videoid
 * 27.新建存储评论的集合 content  videoid  userid  
 * 28.在视频的集合 添加 commnetcount 评论的数量 
 * 
 * 
 * 29.视频的评论列表和删除评论 、commentlist/:videoid  不需要登陆
 * 30.也是使用分页进行查询
 * 31 删除评论  使用delete方法 comment/videoid/comementid
 * 32 判断视频到底存不存在 此条评论到底存不存在
 * 33 判断删除的评论是否与登陆者的评论  .equal进行对比 
 * 34 使用remove 进行删除  删除后也要把video集合中把评论数量-1
 * 
 * 
 * 35 喜欢与不喜欢视频
 * 36 get /like/videoid  新建videolike的集合 保存喜欢或者不喜欢
 * 37 键值  userid  videoid  like(1|| -1) {enmu:[1,-1]}
 * 38 判断视频是否存在 判断视频之前是否是喜欢还是不喜欢的状态  取反
 * 39 在video 加入likecount  unlikecount 表示喜欢和不喜欢的数量
 * 40 在修改videolike集合对喜欢和不喜欢的数量进行处理
 * 41 返回的结果要包含当前是喜欢海曙不喜欢
 * 42 dislike/videoid 
 * 
 * 
 * 
 * 43 喜欢的视频列   /likelist  要先登陆
 * 44 分页显示 
 * 45 获取视频详情优化  如果登陆的情况 返回喜欢不喜欢 关注作者的情况 返回的结果带
 * islike isdislike issubscribt 
 * 
 * 
 * 46修改视频接口  删除视频接口
 * 
 * 
 * 
 */


/**
 * Redis缓存
 * 
 * 47什么是Redis
 * 
 * 48 安装redis 
 * 
 * 49 redis key的命名规则  
 * 
 * 50列表操作 存储有序数组  lpush l1 123
 * 51 linsert l1 before 88 44
 * 52 集合
 * 53 有序集合
 * 54 zincrby z1 1 u2
 * 55删除有序集合  zrem z1 u2
 * 
 * 
 * 
 * 56 node操作redis ioredis
 * 
 * 
 * 57 linux   an vim编辑器 
 * 
 * 
 * 58 有序集合实现排名 
 * 59 使用到zadd zscore zincreby zreverange获取从大到小的排序
 * 60 书写一个方法  模仿导出最热视频 返回{键值：热度值}
 * 
 * 61 视频收藏功能 视频热门推荐机制  点赞收藏转发  再提高一个推荐热门视频的接口
 * 62 新建一个collectModel mongoose 视频收藏的集合
 * 63 /getcollect/videoid  收藏视频的方法 判断视频是否存在  判断视频已经收藏
 * 
 * 
 * 64 热门视频的推荐机制   观看+1 点赞+2  评论+2 收藏+3 类似于一键3连
 * 65 封装redis 在model内新建redis文件夹 npm i redis 
 * 66 封装热门链接的方法  redishotsinc   导出hotInc 
 * 
 * 67 获取热门推荐视频接口
 * 68 在redis 导出  topHots (num )
 * 69 新建/gethots接口  不用登陆验证
 * 
 * 
 * 
 * 70 云服务器与Nginx代理
 * 71 在linx中安装node mongodb redis
 * 
 * 72nginx 反向代理 负载均衡
 * 73nginx 安装与基本使用 
 * 74 sudo apt-get install nginx 直接安装
 * 74 cd /usr/share# 
 * 75 cd /etc/nginx/config  配置文件
 * 76cd /var/
 * 77 cd log/
 * 78 cd nginx/ access error  运行错误日志
 * 
 * 
 * 79.nginx的工作模型和常用命令 Master主进程只接收和分配到子进程 
 * 80.常用的命令 关闭:nginx -s stop(立马停止) |    nginx -s -quiet(等待子进程运行完成并且不再接受新的请求)  启动：nginx
 * 81.vim access.log 查看日志 
 * mv access.log 22.log   修改文件名
 * touch access.log  创建文件
 * nginx -s reopen 重新打开 让磁盘重新读写日志文件名
 * nginx -s rerload  重新加载配置文件
 * nginx -t  检查配置文件格式是否有错误
 * 
 * 
 * nginx的配置文件
 * 
 * main 全局配置区
 * 
 * 
 * event 事件区  子进程核心配置
 * 
 * worker_connections:768 每个子进程最多可以处理768指令数
 * 
 * 
 * 
 * 
 * http 服务器配置区
 * 
 * sendfile:on  调用系统的输出文件
 * keeplive_timeout 几秒时候断开连接
 * inclue   外部包
 * 
 * 
 * 
 * 
 * mail 邮件代理配置区
 * 
 * 
 * 
 * 
 * 
 * 82 nginx和node进行配合  nginx的反向代理
 * 83 filezilla  给服务器发生文件
 * 84 sites-enabled的文件夹内  的location属性内 proxy_pass HTTP://127.0.0.1:3000
 * 
 * 
 * 
 * 
 * 项目的部署和域名的解析
 * 
 * 
 * https配置  申请证书
 * 
 * 发布npm 包
 * 
 * 
 * 
 * 
 * 
 * 
 * 85 koa框架  使用es6进行编写
 * 86 使用的use req,res方法都封装在ctx内  app.use(async ctx=>{
 *      
 * })
 * 
 * 87 ctx.body(返回数据)  ctx.req.mehod  ctx.path ctx.req.url ctx.params ctx.req.header ctx.query
 * 
 * 
 * 88.中间件和异步执行逻辑  洋葱圈模型
 * 89. (ctx,next) next执行后才会到下一步执行
 * 90. 代码中间有next执行后 会跳到下一个中间间 如果下一个中间件next执行完之后没有中间件了
 * 会跳到最外层的中间件 执行next后面的代码 这样就是洋葱圈模型
 * 91. 如果是异步 async await 会和同步的中间件有不一样
 * 
 * 
 * koa的路由处理模块
 * 92 koa的路由和参数的获取   
 * 93 @koa/router 安装中间件 router.post router.get('/user,(ctx)=>{})
 * 94 app.use(router.routes())
 * 95 进行模块化的拆分 设置路由的前缀   const router = new Router({prefix:'api/v1'})
 * 
 * 
 * 
 * 
 * 
 * koa获取参数
 * 96 ctx.query  ctx.params 
 * 97 获取post请求的参数  使用插件 koa-body 使用app.use()进行挂载  获取不到form-data数据 解决方法 查看koa-body的git文档
 * 
 * 98 koa错误异常接管 ctx.throw(400,'errormsg') ctx.throw(500,'errormsg')指定500系列的不会返回给客户端
 * 99 事件监听  app.on('error',(err,ctx)=>{ctx.body(对客户端进行返回)})
 * 
 * koa重构代码
 * 
 * 
 * 100 基础设置  安装 koa @koa/router koa-body koa-cors 等等
 * 
 * 101 连接数据库
 * 
 * 102 通用数据验证  joi 验证工具 自定义验证 
 * 
 */
